package cn.schoolwow.quickdao.module.database.dml.instance.flow.delete.common;

import cn.schoolwow.quickdao.domain.QuickDAOConfig;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickdao.module.database.parent.domain.GetStatementSupplier;
import cn.schoolwow.quickdao.module.database.parent.flow.GetAndCacheStatementFlow;
import cn.schoolwow.quickdao.module.database.parent.flow.executor.ExecuteUpdateConnectionFlow;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.instance.QueryInstance;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DeleteBySingleUniqueKeyFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setStatement(flowContext);
        setParameters(flowContext);
        executeStatement(flowContext);
    }

    @Override
    public String name() {
        return "根据单个唯一约束字段删除实例";
    }

    private void setStatement(FlowContext flowContext) {
        QuickDAOConfig quickDAOConfig = flowContext.checkInstanceData(QuickDAOConfig.class);
        Entity entity = (Entity) flowContext.checkData("entity");
        Property uniqueKeyProperty = (Property) flowContext.checkData("uniqueKeyProperty");
        Object instance = flowContext.getData("instance");

        StringBuilder sqlBuilder = new StringBuilder();
        if(null!=instance){
            flowContext.startFlow(new GetAndCacheStatementFlow())
                    .putReturnData("sqlCacheName", "deleteBySingleUniqueKey_"+entity.tableName+"_"+uniqueKeyProperty.column)
                    .putInstanceData(new GetStatementSupplier() {
                        @Override
                        public String getStatement() {
                            return "delete from " + quickDAOConfig.databaseContext.databaseProvider.escape(entity.tableName) + " where " + quickDAOConfig.databaseContext.databaseProvider.escape(uniqueKeyProperty.column) + " = ?";
                        }
                    }, GetStatementSupplier.class)
                    .execute();
        }else{
            Object[] instances = (Object[]) flowContext.checkData("instances");
            sqlBuilder.append("delete from " + quickDAOConfig.databaseContext.databaseProvider.escape(entity.tableName) + " where " + quickDAOConfig.databaseContext.databaseProvider.escape(uniqueKeyProperty.column) + " in (");
            for(int i=0;i<instances.length;i++){
                sqlBuilder.append("?,");
            }
            sqlBuilder.deleteCharAt(sqlBuilder.length() - 1);
            sqlBuilder.append(")");
            flowContext.putData("sql", sqlBuilder.toString());
        }
    }

    public void setParameters(FlowContext flowContext) {
        Entity entity = (Entity) flowContext.checkData("entity");
        Property uniqueKeyProperty = (Property) flowContext.checkData("uniqueKeyProperty");
        Object instance = flowContext.getData("instance");

        if(null!=instance){
            Object value = QueryInstance.newQuery(instance)
                    .execute()
                    .getSingleFieldValue(uniqueKeyProperty.name);
            if(null==value){
                throw new IllegalArgumentException("唯一约束字段不能为空!实体类:"+entity.clazz.getName()+",字段名:"+uniqueKeyProperty.name);
            }
            flowContext.putTemporaryData("parameters", Arrays.asList(value));
        }else{
            Object[] instances = (Object[]) flowContext.checkData("instances");
            List<Object> parameters = new ArrayList();
            for(int i=0;i<instances.length;i++){
                Object value = QueryInstance.newQuery(instances[i])
                        .execute()
                        .getSingleFieldValue(uniqueKeyProperty.name);
                if(null==value){
                    throw new IllegalArgumentException("唯一约束字段不能为空!实体类:"+entity.clazz.getName()+",字段名:"+uniqueKeyProperty.name);
                }
                parameters.add(value);
            }
            flowContext.putTemporaryData("parameters", parameters);
        }
    }

    private void executeStatement(FlowContext flowContext) {
        flowContext.startFlow(new ExecuteUpdateConnectionFlow())
                .putTemporaryData("name", "根据单个唯一约束字段删除实例")
                .execute();
    }
}
